#pragma once

#include "common.hpp"


// //                                  socket_fd
// using func_t = std::function<void(int, int)>;//包装一切参数和返回值相同的可调用对象: 函数指针, lambda, 仿函数...
// //                         listen_socket_fd,

using func_t = std::function<void(int)>;

using task_t = std::function<void(void)>;//thread_pool版本的service


class server_tcp : public no_copy
{
private:
    void init()
    {
        //1.创建socket
        _listen_socket_fd = socket(AF_INET, SOCK_STREAM, 0);//前两个参数组合代表TCP协议通信
        if(_listen_socket_fd < 0)
        if(_listen_socket_fd < 0)
        {
            LOG(wzx::log_level::FATAL) << "listen_socket_fd construct failed!!!";
            exit(LISTEN_SOCKFD_CON_ERR);
        }
        LOG(wzx::log_level::INFO) << "listen_socket_fd construct successfully, _socket_fd: " << _listen_socket_fd;

        //2.绑定信息
        //2.1.创建并设置sockaddr结构
        Inet_Addr tmp(_port);
        
        //2.2.绑定至内核
        int ret_bind = bind(_listen_socket_fd, (const sockaddr*)(&tmp.get_addr()), sizeof(tmp.get_addr()));
        if(ret_bind < 0)
        {
            LOG(wzx::log_level::FATAL) << "bind failed!!!";
            exit(BIND_ERR);
        }
        LOG(wzx::log_level::INFO) << "bind successfully...";

        //3.设置_listen_socket_fd为监听状态 -- tcp特有
        #define BACKLOG 8 //允许最大连接请求数
        int ret_listen = listen(_listen_socket_fd, BACKLOG);
        if(ret_listen < 0)
        {
            LOG(wzx::log_level::FATAL) << "listen failed!!!";
            exit(LISTEN_ERR);
        }
        LOG(wzx::log_level::INFO) << "listen successfully...";

    }

public:
    server_tcp(uint16_t port, const func_t& handle_func)
        :_port(port)
        ,_running_tag(false)
        ,_handle_func(handle_func)
    {
        init();
    }

    void start()
    {
        _running_tag = true;

        while(_running_tag)
        {
            //4.获取连接
            struct sockaddr_in client_addr;
            socklen_t len = sizeof(client_addr);
            //                                                     输出           输入输出
            int socket_fd = accept(_listen_socket_fd, (sockaddr*)(&client_addr), &len);
            if(socket_fd < 0)
            {
                LOG(wzx::log_level::WARNING) << "accept failed~~";
                continue;//获取失败就继续获取别的(张三吆喝失败接着找下一个路人)
            }
            Inet_Addr client(client_addr);
            LOG(wzx::log_level::INFO) << "accept successfully... " << client.get_ip() << " " << client.get_port();

            //5.提供服务
            // _handle_func(_listen_socket_fd, socket_fd);
            _handle_func(socket_fd);
        }
    }

    

private:
    int _listen_socket_fd;//监听套接字, 只负责获取新连接
    uint16_t _port;
    // std::string _ip; --> INADDR_ANY

    bool _running_tag;
    func_t _handle_func;//可以接受一切参数和返回值相同的可调用对象: 函数指针, lambda, 仿函数...
};